﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using System.IO;
using System.Collections;

namespace 智能赋予高程值
{
    public partial class Form1 : Form
    {
        Autodesk.AutoCAD.Interop.AcadApplication AcadApp;
        Autodesk.AutoCAD.Interop.AcadDocument AcadDoc;

        ArrayList ElvPoints;
        ArrayList ElvPointsObj;//高程注记对象
        ArrayList ElvPointsCoord;//高程注记对象坐标

        public Form1()
        {
            InitializeComponent();
        }

        private void 启动CAD()
        {
            try
            {
                AcadApp =
               (AcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject("AutoCAD.Application");
                AcadDoc = AcadApp.ActiveDocument;
            }
            catch
            {
                OpenFileDialog pOpenDG = new OpenFileDialog();
                pOpenDG.Filter = "CAD文件(*.dwg)|*.dwg|CAD图形文件(*.dxf)|*.dxf";
                pOpenDG.Title = "打开CAD文件";
                pOpenDG.ShowDialog();
                string filePath = pOpenDG.FileName;
                if (filePath == "")
                {
                    MessageBox.Show("选择CAD文件无效！", "文件无效！");
                    Application.Exit();
                }
                AcadApp = new AcadApplication();
                AcadDoc = AcadApp.Documents.Open(filePath, null, null);
            }
            AcadApp.Application.Visible = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            启动CAD();
            RefreshLayersName();
        }

        private void 获取高程注记对象button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (TextLayerComboBox.Text != "")
                {
                    ElvPoints = new ArrayList();
                    //首先获取指定高程注记图层中的所有图形对象
                    AcadSelectionSet mySelectionSet;
                    mySelectionSet = AcadDoc.SelectionSets.Add("NewSelectionSet01");
                    Int16[] FilterType = new Int16[1];
                    object[] FilterData = new object[1];
                    FilterType[0] = 8;
                    FilterData[0] = TextLayerComboBox.Text;
                    double[] point01 = new double[3];
                    double[] point02 = new double[3];
                    point01[0] = 0; point01[1] = 0; point01[2] = 0;
                    point02[0] = 1000; point02[1] = 1000; point02[2] = 0;
                    mySelectionSet.Select(AcSelect.acSelectionSetAll, point01, point02, FilterType,
                   FilterData);
                    bool isNumber;//是否为数字
                    double elvNumber;//高程值
                    string objectString;//文字内容
                                        //然后在选择集中寻找符合要求的图形对象，即AcDbText和AcDbMText对象
                    foreach (AcadObject cadObject in mySelectionSet)
                    {
                        if (cadObject.ObjectName == "AcDbText")
                        {
                            objectString = ((AcadText)cadObject).TextString.ToString();
                            isNumber = double.TryParse(objectString, out elvNumber);
                            if (isNumber)
                                ElvPoints.Add(cadObject);
                        }
                        else if (cadObject.ObjectName == "AcDbMText")
                        {
                            objectString = ((AcadMText)cadObject).TextString.ToString();
                            isNumber = double.TryParse(objectString, out elvNumber);
                            if (!isNumber)
                            {
                                if (objectString.Contains("{") & objectString.Contains("}") &
                               objectString.Contains(";"))
                                {
                                    objectString =
                                   objectString.Substring(objectString.LastIndexOf(";") + 1, objectString.Length -
                                   objectString.LastIndexOf(";") - 2);
                                    isNumber = double.TryParse(objectString, out elvNumber);
                                }
                            }
                            if (isNumber)
                                ElvPoints.Add(cadObject);
                        }
                    }
                    MessageBox.Show("共有高程注记对象个数为：" + ElvPoints.Count.ToString());
                    AcadDoc.SelectionSets.Item("NewSelectionSet01").Delete();
                }
            }
            catch (Exception except)
            {
                MessageBox.Show(except.Message);
            }
        }

        private void 连接高程注记button_Click(object sender, EventArgs e)
        {
            //新建图层“高程值辅助线”
            bool isIn = false;
            for (int i = 0; i < AcadDoc.Layers.Count; i++)
            {
                if (AcadDoc.Layers.Item(i).Name == "高程值辅助线")
                {
                    isIn = true;
                    break;
                }
            }
            if (isIn)
            {
                MessageBox.Show("文件中存在图层“高程值辅助线”，请修改该图层名称！");
                return;
            }
            else
            {
                AcadLayer pLayer = AcadDoc.Layers.Add("高程值辅助线");
                pLayer.color = AcColor.acRed;
            }
            //定义用于保存高程值辅助线各点坐标的动态数组
            ArrayList tempPointLine;
            if (ElvPointsObj != null)
            {
                int i, j;
                while (ElvPointsCoord.Count > 0)
                {
                    tempPointLine = new ArrayList();
                    //寻找最大、最小高程值
                    double maxElv, minElv;
                    double[] maxCoord;
                    //排序
                    IComparer comparer = new myMaxSortClass();
                    ElvPointsCoord.Sort(comparer);
                    maxElv = ((double[])ElvPointsCoord[0])[2];
                    minElv = ((double[])ElvPointsCoord[ElvPointsCoord.Count - 1])[2];
                    //为直线添加第一个点
                    maxCoord = (double[])ElvPointsCoord[0];
                    tempPointLine.Add(maxCoord);
                    //删除最大值
                    ElvPointsCoord.RemoveAt(0);
                    double[] tempPointCoords;
                    i = 0;
                    //寻找比最大值小的高程值
                    while (maxElv > minElv)
                    {
                        tempPointCoords = (double[])ElvPointsCoord[i];
                        if (tempPointCoords[2] < maxElv)//在下一级高程值中寻找最近点
                        {
                            //首先获取具有相同下一级高程值的点数
                            for (j = i; j < ElvPointsCoord.Count; j++)
                            {
                                double[] tempPointCoords02 = (double[])ElvPointsCoord[j];
                                if (tempPointCoords02[2] < tempPointCoords[2])
                                {
                                    break;
                                }
                            }
                            //然后在这j个点中寻找与maxElv最大值点最近的点
                            double[] pointsCoords = new double[3 * (j - i)];
                            for (int k = 0; k < pointsCoords.Length / 3; k++)
                            {
                                pointsCoords[3 * k] = ((double[])ElvPointsCoord[i + k])[0];
                                pointsCoords[3 * k + 1] = ((double[])ElvPointsCoord[i + k])[1];
                                pointsCoords[3 * k + 2] = ((double[])ElvPointsCoord[i + k])[2];
                            }
                            int tempNearInt = GetNearPoint(maxCoord, pointsCoords);
                            //为直线添加高程点并把最大值赋给它
                            maxCoord = (double[])ElvPointsCoord[tempNearInt + i];
                            maxElv = maxCoord[2];
                            tempPointLine.Add(maxCoord);
                            //然后删除这个点
                            ElvPointsCoord.RemoveAt(tempNearInt + i);
                        }
                        else
                        {
                            i++;
                        }
                    }
                    //绘制三维多段线
                    if (tempPointLine != null)
                    {
                        //首先获取多段线上的节点坐标
                        double[] polylineCoords = new double[3 * tempPointLine.Count];
                        double[] tempPolylineCoords;
                        for (i = 0; i < tempPointLine.Count; i++)
                        {
                            tempPolylineCoords = (double[])tempPointLine[i];
                            polylineCoords[3 * i] = tempPolylineCoords[0];
                            polylineCoords[3 * i + 1] = tempPolylineCoords[1];
                            polylineCoords[3 * i + 2] = tempPolylineCoords[2];
                        }
                        //然后在图层“高程值辅助线”中绘制多段线
                        Acad3DPolyline temp3DPolyObj =
                       AcadDoc.ModelSpace.Add3DPoly(polylineCoords);
                        temp3DPolyObj.Layer = "高程值辅助线";
                    }
                }
            }
            //刷新图层
            RefreshLayersName();
        }

        /// <summary> 
        /// 比较一点与其他点集中的最近点
        /// </summary> 
        /// <param name="originPoint">比较的点，长度为3</param> 
        /// <param name="comparaPoints">点集中的点，长度为3*N</param> 
        /// <returns>返回点集中点的序号，从0开始</returns> 
        private int GetNearPoint(double[] originPoint, double[] comparaPoints)
        {
            int returnInt = 0;
            int pointsCount = comparaPoints.Length / 3;
            double min = Math.Sqrt((originPoint[0] - comparaPoints[0]) * (originPoint[0] -
           comparaPoints[0]) +
            (originPoint[1] - comparaPoints[1]) * (originPoint[1] - comparaPoints[1]));
            double tempmin;
            for (int i = 1; i < pointsCount; i++)
            {
                tempmin = Math.Sqrt((originPoint[0] - comparaPoints[3 * i]) * (originPoint[0] -
               comparaPoints[3 * i]) +
                (originPoint[1] - comparaPoints[3 * i + 1]) * (originPoint[1] - comparaPoints[3 * i
               + 1]));
                if (tempmin < min)
                {
                    min = tempmin;
                    returnInt = i;
                }
            }
            return returnInt;
        }

        /// <summary> 
        /// 刷新显示图层
        /// </summary> 
        private void RefreshLayersName()
        {
            if (AcadDoc != null)
            {
                TextLayerComboBox.Items.Clear();
                ContoursComboBox.Items.Clear();
                for (int i = 0; i < AcadDoc.Layers.Count; i++)
                {
                    TextLayerComboBox.Items.Add(AcadDoc.Layers.Item(i).Name);
                    ContoursComboBox.Items.Add(AcadDoc.Layers.Item(i).Name);
                }
            }
        }

        private void 赋予高程值button_Click(object sender, EventArgs e)
        {
            //用于赋予高程值的等高线对象的句柄
            ArrayList ContoursHandleID = new ArrayList();
            //新建的等高线对象，其数目与ContoursHandleID数目相同
            ArrayList NewContours = new ArrayList();
            //新建图层“自动等高线”
            bool isIn = false;
            for (int i = 0; i < AcadDoc.Layers.Count; i++)
            {
                if (AcadDoc.Layers.Item(i).Name == "自动等高线")
                {
                    isIn = true;
                    break;
                }
            }
            if (isIn)
            {
                MessageBox.Show("文件中存在图层“自动等高线”，请修改该图层名称！");
                return;
            }
            else
            {
                AcadLayer pLayer = AcadDoc.Layers.Add("自动等高线");
                pLayer.color = AcColor.acGreen;
            }
            //判断“高程值辅助线”是否存在
            isIn = false;
            for (int i = 0; i < AcadDoc.Layers.Count; i++)
            {
                if (AcadDoc.Layers.Item(i).Name == "高程值辅助线")
                {
                    isIn = true;
                    break;
                }
            }
            if (isIn)//如果存在则选择三维多段线
            {
                AcadSelectionSet mySelectionSet;
                mySelectionSet = AcadDoc.SelectionSets.Add("NewSelectionSet02");
                Int16[] FilterType = new Int16[1];
                object[] FilterData = new object[1];
                FilterType[0] = 8;
                FilterData[0] = "高程值辅助线";
                double[] point01 = new double[3];
                double[] point02 = new double[3];
                point01[0] = 0; point01[1] = 0; point01[2] = 0;
                point02[0] = 1000; point02[1] = 1000; point02[2] = 0;
                mySelectionSet.Select(AcSelect.acSelectionSetAll, point01, point02, FilterType,
               FilterData);
                if (mySelectionSet.Count > 0)
                {
                    double[] polyCoords;
                    double[] tempLineCoords;
                    double[] selectionEdge;
                    double[] tempContoursCoord;
                    int i;
                    foreach (AcadObject tempCadObject in mySelectionSet)
                    {
                        if (tempCadObject.ObjectName == "AcDb3dPolyline")
                        {
                            Acad3DPolyline temp3DPoly = (Acad3DPolyline)tempCadObject;
                            polyCoords = (double[])temp3DPoly.Coordinates;
                            for (i = 0; i < polyCoords.Length / 3 - 1; i++)
                            {
                                tempLineCoords = new double[6];
                                tempLineCoords[0] = polyCoords[3 * i];
                                tempLineCoords[1] = polyCoords[3 * i + 1];
                                tempLineCoords[2] = polyCoords[3 * i + 2];
                                tempLineCoords[3] = polyCoords[3 * i + 3];
                                tempLineCoords[4] = polyCoords[3 * i + 4];
                                tempLineCoords[5] = polyCoords[3 * i + 5];
                                //设置选择范围边界
                                selectionEdge = new double[15];
                                selectionEdge[0] = tempLineCoords[0];
                                selectionEdge[1] = tempLineCoords[1];
                                selectionEdge[2] = 0d;
                                selectionEdge[3] = tempLineCoords[3];
                                selectionEdge[4] = tempLineCoords[1];
                                selectionEdge[5] = 0d;
                                selectionEdge[6] = tempLineCoords[3];
                                selectionEdge[7] = tempLineCoords[4];
                                selectionEdge[8] = 0d;
                                selectionEdge[9] = tempLineCoords[0];
                                selectionEdge[10] = tempLineCoords[4];
                                selectionEdge[11] = 0d;
                                selectionEdge[12] = tempLineCoords[0];
                                selectionEdge[13] = tempLineCoords[1];
                                selectionEdge[14] = 0d;
                                //长度为3*n，第一个数据表示对象的Handle值
                                //第二个数据表示等高线节点坐标，长度为2*m 
                                //第三个数据表示与线段的交点坐标，长度为2 
                                ArrayList tempContoursArray = new ArrayList();
                                //定义选择集
                                AcadSelectionSet tempSelectionSet;
                                tempSelectionSet =
                               AcadDoc.SelectionSets.Add("TempNewSelectionSet01");
                                FilterType[0] = 8;
                                FilterData[0] = ContoursComboBox.Text;

                                tempSelectionSet.SelectByPolygon(AcSelect.acSelectionSetCrossingPolygon, selectionEdge,
                                FilterType, FilterData);
                                double[] tempContoursCoord02, intersectCoord;
                                bool tempResult;
                                if (tempSelectionSet.Count > 0)
                                {
                                    foreach (AcadObject tempAcadObj in tempSelectionSet)
                                    {
                                        switch (tempAcadObj.ObjectName)
                                        {
                                            case "AcDbPolyline"://如果为多段线
                                                AcadLWPolyline tempLWPolyline =
                                               (AcadLWPolyline)tempAcadObj;
                                                tempContoursCoord =
                                               (double[])tempLWPolyline.Coordinates;
                                                //判断与直线的关系
                                                tempResult = JudgeCrossStatus(tempContoursCoord,
                                               tempLineCoords, out intersectCoord);
                                                if (tempResult)
                                                {
                                                    tempContoursArray.Add(tempLWPolyline.Handle);
                                                    tempContoursArray.Add(tempContoursCoord);
                                                    tempContoursArray.Add(intersectCoord);
                                                }
                                                break;
                                            case "AcDb2dPolyline"://如果为二维多段线
                                                AcadPolyline tempPolyline =
                                               (AcadPolyline)tempAcadObj;
                                                tempContoursCoord02 =
                                               (double[])tempPolyline.Coordinates;
                                                tempContoursCoord = new double[2 *
                                               tempContoursCoord02.Length / 3];
                                                for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                                {
                                                    tempContoursCoord[2 * j] =
                                                   tempContoursCoord02[3 * j];
                                                    tempContoursCoord[2 * j + 1] =
                                                   tempContoursCoord02[3 * j + 1];
                                                }
                                                //判断与直线的关系
                                                tempResult = JudgeCrossStatus(tempContoursCoord,
                                               tempLineCoords, out intersectCoord);
                                                if (tempResult)
                                                {
                                                    tempContoursArray.Add(tempPolyline.Handle);
                                                    tempContoursArray.Add(tempContoursCoord);
                                                    tempContoursArray.Add(intersectCoord);
                                                }
                                                break;
                                            case "AcDbSpline"://如果为样条曲线
                                                AcadSpline tempSpline = (AcadSpline)tempAcadObj;
                                                tempContoursCoord02 =
                                               (double[])tempSpline.ControlPoints;
                                                tempContoursCoord = new double[2 *
                                               tempContoursCoord02.Length / 3];
                                                for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                                {
                                                    tempContoursCoord[2 * j] =
                                                   tempContoursCoord02[3 * j];
                                                    tempContoursCoord[2 * j + 1] =
                                                   tempContoursCoord02[3 * j + 1];
                                                }
                                                //判断与直线的关系
                                                tempResult = JudgeCrossStatus(tempContoursCoord,
                                               tempLineCoords, out intersectCoord);
                                                if (tempResult)
                                                {
                                                    tempContoursArray.Add(tempSpline.Handle);
                                                    tempContoursArray.Add(tempContoursCoord);
                                                    tempContoursArray.Add(intersectCoord);
                                                }
                                                break;
                                            case "AcDb3dPolyline"://如果为三维多段线
                                                Acad3DPolyline temp3dPoly =
                                               (Acad3DPolyline)tempAcadObj;
                                                tempContoursCoord02 =
                                               (double[])temp3dPoly.Coordinates;
                                                tempContoursCoord = new double[2 *
                                               tempContoursCoord02.Length / 3];
                                                for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                                {
                                                    tempContoursCoord[2 * j] =
                                                   tempContoursCoord02[3 * j];
                                                    tempContoursCoord[2 * j + 1] =
                                                   tempContoursCoord02[3 * j + 1];
                                                }
                                                //判断与直线的关系
                                                tempResult = JudgeCrossStatus(tempContoursCoord,
                                               tempLineCoords, out intersectCoord);
                                                if (tempResult)
                                                {
                                                    tempContoursArray.Add(temp3dPoly.Handle);
                                                    tempContoursArray.Add(tempContoursCoord);
                                                    tempContoursArray.Add(intersectCoord);
                                                }
                                                break;
                                        }
                                    }
                                }
                                //赋予高程值
                                if (tempContoursArray.Count > 0)
                                {
                                    //等高距
                                    double intervalElv = (tempLineCoords[2] - tempLineCoords[5]) / (tempContoursArray.Count / 3 + 1);
                                    double tempPolyElevation;
                                    double[] tempDrawPolyline, tempDrawPolyline02,
                                   tempIntersectCoords;
                                    AcadPolyline tempDrawContour;
                                    //等高线与线段交点坐标
                                    tempIntersectCoords = new double[2 * tempContoursArray.Count / 3];
                                    for (int j = 0; j < tempContoursArray.Count / 3; j++)
                                    {
                                        tempDrawPolyline02 = (double[])tempContoursArray[3 * j + 2];
                                        tempIntersectCoords[2 * j] = tempDrawPolyline02[0];
                                        tempIntersectCoords[2 * j + 1] = tempDrawPolyline02[1];
                                    }
                                    int[] contourIndex;//等高线顺序，从0开始
                                    contourIndex = PointsSort(tempLineCoords, tempIntersectCoords);
                                    for (int j = 0; j < tempContoursArray.Count / 3; j++)
                                    {
                                        //根据等高线交点排序来设置等高线的高程值
                                        tempDrawPolyline02 = (double[])tempContoursArray[3 * j + 1];
                                        tempPolyElevation = tempLineCoords[2] - (contourIndex[j] +
                                       1) * intervalElv;
                                        //先判断是否已经为该对象赋予高程值了
                                        string tempObjectHandle = (string)tempContoursArray[3 * j];
                                        if (!ContoursHandleID.Contains(tempObjectHandle))//如果不包含该Handle值
                                        {
                                            tempDrawPolyline = new double[3 *
                                           tempDrawPolyline02.Length / 2];
                                            for (int k = 0; k < tempDrawPolyline02.Length / 2; k++)
                                            {
                                                tempDrawPolyline[3 * k] = tempDrawPolyline02[2 * k];
                                                tempDrawPolyline[3 * k + 1] = tempDrawPolyline02[2 * k + 1];
                                                tempDrawPolyline[3 * k + 2] = tempPolyElevation;
                                            }
                                            tempDrawContour =
                                           AcadDoc.ModelSpace.AddPolyline(tempDrawPolyline);
                                            tempDrawContour.Elevation = tempPolyElevation;
                                            tempDrawContour.Layer = "自动等高线";
                                            ContoursHandleID.Add(tempObjectHandle);
                                            NewContours.Add(tempDrawContour);
                                        } 
                                        else//如果已经存在，则判断一下现在获取高程值与以前设置是否相同，
                                            //如果不同则设置线的颜色为黄色，表示警告！
                                        {
                                            AcadPolyline tempDrawContour02 =
                                           (AcadPolyline)NewContours[ContoursHandleID.IndexOf(tempObjectHandle)];
                                            if (tempDrawContour02.Elevation != tempPolyElevation)
                                                tempDrawContour02.color = ACAD_COLOR.acYellow;
                                        }
                                    }
                                }
                                AcadDoc.SelectionSets.Item("TempNewSelectionSet01").Delete();
                            }
                        }
                    }
                }
                AcadDoc.SelectionSets.Item("NewSelectionSet02").Delete();
            }
        }

        /// <summary> 
        /// 初步根据外围框大致判断两条线段是否相交
        /// </summary> 
        /// <param name="line01Coords">线段1的坐标，长度为6</param> 
        /// <param name="line02Coords">线段2的坐标，长度为6</param> 
        /// <returns>返回类型为bool，如果为true表示两条线段可能相交，如果为false表示两条线段不相交</returns> 
        private bool JudgeAboutCrossStatus(double[] line01Coords, double[] line02Coords)
        {
            bool returnResult = true;
            //先判断在XY方向的最值
            double maxX1, minX1, maxY1, minY1;
            maxX1 = minX1 = line01Coords[0];
            maxY1 = minY1 = line01Coords[1];
            if (line01Coords[0] < line01Coords[3])
                maxX1 = line01Coords[3];
            else
                minX1 = line01Coords[3];
            if (line01Coords[1] < line01Coords[4])
                maxY1 = line01Coords[4];
            else
                minY1 = line01Coords[4];
            double maxX2, minX2, maxY2, minY2;
            maxX2 = minX2 = line02Coords[0];
            maxY2 = minY2 = line02Coords[1];
            if (line02Coords[0] < line02Coords[3])
                maxX2 = line02Coords[3];
            else
                minX2 = line02Coords[3];
            if (line02Coords[1] < line02Coords[4])
                maxY2 = line02Coords[4];
            else
                minY2 = line02Coords[4];
            //比较最值大小
            if ((minX1 > maxX2) || (maxX1 < minX2) || (minY1 > maxY2) || (maxY1 < minY2))
            {
                returnResult = false;
            }
            return returnResult;
        }

        /// <summary> 
        /// 判断两条线段是否相交
        /// </summary> 
        /// <param name="line01Coords">线段1的坐标，长度为6</param> 
        /// <param name="line02Coords">线段2的坐标，长度为6</param> 
        /// <returns>返回类型为bool，如果为true表示两条线段相交，如果为false表示两条线段不相交</returns> 
        private bool Judge2LinesRelation(double[] line01Coords, double[] line02Coords)
        {
            bool returnResult = true;
            returnResult = JudgeAboutCrossStatus(line01Coords, line02Coords);
            if (returnResult)//初步判断两条线段可能相交
            {
                double BAx, BAy, BCx, BCy, BDx, BDy, BABCk, BABDk;
                BAx = line01Coords[0] - line01Coords[3];
                BAy = line01Coords[1] - line01Coords[4];
                BCx = line02Coords[0] - line01Coords[3];
                BCy = line02Coords[1] - line01Coords[4];
                BABCk = BAx * BCy - BAy * BCx;
                BDx = line02Coords[3] - line01Coords[3];
                BDy = line02Coords[4] - line01Coords[4];
                BABDk = BAx * BDy - BAy * BDx;
                if (((BABCk > 0) && (BABDk > 0)) || ((BABCk < 0) && (BABDk < 0)))
                {
                    returnResult = false;
                }
                else if (((BABCk > 0) && (BABDk < 0)) || ((BABCk < 0) && (BABDk > 0)))
                {
                    double BCBDk;
                    BCBDk = BCx * BDy - BCy * BDx;
                    if (((BABDk > 0) && (BCBDk > 0)) || ((BABDk < 0) && (BCBDk < 0)))
                    {
                        returnResult = true;
                    }
                    else
                    {
                        returnResult = false;
                    }
                }
                else if ((BABCk == 0) || (BABDk == 0))//点C或D在直线AB上
                {
                    double[] templine02Coords = new double[3];
                    if (BABCk == 0)//点C在直线AB上
                    {
                        templine02Coords[0] = line02Coords[0];
                        templine02Coords[1] = line02Coords[1];
                        templine02Coords[2] = line02Coords[2];
                    }
                    else//点D在直线AB上
                    {
                        templine02Coords[0] = line02Coords[3];
                        templine02Coords[1] = line02Coords[4];
                        templine02Coords[2] = line02Coords[5];
                    }
                    if (line01Coords[0] == line01Coords[3])//是否垂直，是则比较Y值
                    {
                        double maxY, minY;
                        maxY = minY = line01Coords[1];
                        if (line01Coords[1] < line01Coords[4])
                            maxY = line01Coords[4];
                        else
                            minY = line01Coords[4];
                        if ((templine02Coords[1] >= minY) && (templine02Coords[1] <= maxY))//在线段上
                             returnResult = true;
                        else
                            returnResult = false;
                    }
                    else //比较X值
                    {
                        double maxX, minX;
                        maxX = minX = line01Coords[0];
                        if (line01Coords[0] < line01Coords[3])
                            maxX = line01Coords[3];
                        else
                            minX = line01Coords[3];
                        if ((templine02Coords[0] >= minX) && (templine02Coords[0] <= maxX))//在线段上
                             returnResult = true;
                        else
                            returnResult = false;
                    }
                }
            }
            return returnResult;
        }

        /// <summary> 
        /// 判断两条线段是否相交
        /// </summary> 
        /// <param name="line01Coords">线段 1 的坐标，长度为 6</param> 
        /// <param name="line02Coords">线段 2 的坐标，长度为 6</param> 
        /// <param name="intersectCoord">out,如果有交点则返回交点坐标，长度为 2，否则为 null</param> 
        /// <returns>返回类型为 bool，如果为 true 表示两条线段相交，如果为 false 表示两条线段不相交</returns> 
        private bool Judge2LinesRelation(double[] line01Coords, double[] line02Coords, out double[] intersectCoord)
        {
            intersectCoord = new double[2];
            bool returnResult = true;
            returnResult = JudgeAboutCrossStatus(line01Coords, line02Coords);
            if (returnResult)//初步判断两条线段可能相交
            {
                double BAx, BAy, BCx, BCy, BDx, BDy, BABCk, BABDk;
                BAx = line01Coords[0] - line01Coords[3];
                BAy = line01Coords[1] - line01Coords[4];
                BCx = line02Coords[0] - line01Coords[3];
                BCy = line02Coords[1] - line01Coords[4];
                BABCk = BAx * BCy - BAy * BCx;
                BDx = line02Coords[3] - line01Coords[3];
                BDy = line02Coords[4] - line01Coords[4];
                BABDk = BAx * BDy - BAy * BDx;
                if (((BABCk > 0) && (BABDk > 0)) || ((BABCk < 0) && (BABDk < 0)))
                {
                    returnResult = false;
                }
                else if (((BABCk > 0) && (BABDk < 0)) || ((BABCk < 0) && (BABDk > 0)))
                {
                    double BCBDk;
                    BCBDk = BCx * BDy - BCy * BDx;
                    if (((BABDk > 0) && (BCBDk > 0)) || ((BABDk < 0) && (BCBDk < 0)))
                    {
                        returnResult = true;
                        intersectCoord = Cal2LinesIntersectCoords(line01Coords, line02Coords);
                    }
                    else
                    {
                        returnResult = false;
                    }
                }
                else if ((BABCk == 0) || (BABDk == 0))//点 C 或 D 在直线 AB 上
                {
                    double[] templine02Coords = new double[3];
                    if (BABCk == 0)//点 C 在直线 AB 上
                    {
                        templine02Coords[0] = line02Coords[0];
                        templine02Coords[1] = line02Coords[1];
                        templine02Coords[2] = line02Coords[2];
                    }
                    else//点 D 在直线 AB 上
                    {
                        templine02Coords[0] = line02Coords[3];
                        templine02Coords[1] = line02Coords[4];
                        templine02Coords[2] = line02Coords[5];
                    }
                    if (line01Coords[0] == line01Coords[3])//是否垂直，是则比较 Y 值
                    {
                        double maxY, minY;
                        maxY = minY = line01Coords[1];
                        if (line01Coords[1] < line01Coords[4])
                            maxY = line01Coords[4];
                        else
                            minY = line01Coords[4];
                        if ((templine02Coords[1] >= minY) && (templine02Coords[1] <= maxY))//在线段上
                        {
                            returnResult = true;
                            intersectCoord = Cal2LinesIntersectCoords(line01Coords, line02Coords);
                        }
                        else
                            returnResult = false;
                    }
                    else //比较 X 值
                    {
                        double maxX, minX;
                        maxX = minX = line01Coords[0];
                        if (line01Coords[0] < line01Coords[3])
                            maxX = line01Coords[3];
                        else
                            minX = line01Coords[3];
                        if ((templine02Coords[0] >= minX) && (templine02Coords[0] <= maxX))//在线段上
                        {
                            returnResult = true;
                            intersectCoord = Cal2LinesIntersectCoords(line01Coords, line02Coords);
                        }
                        else
                            returnResult = false;
                    }
                }
            }
            return returnResult;
        }

        /// <summary> 
        /// 计算两条线段的交点
        /// </summary> 
        /// <param name="line01Coords">线段1的坐标，长度为6</param> 
        /// <param name="line02Coords">线段2的坐标，长度为6</param> 
        /// <returns>返回长度为2的数组，表示交点坐标，如果返回为null则表示两条直线平行</returns> 
        private double[] Cal2LinesIntersectCoords(double[] line01Coords, double[] line02Coords)
        {
            double[] returnCoord = new double[3];
            double temp = ((line01Coords[3] - line01Coords[0]) * (line02Coords[4] - line02Coords[1])
                - (line02Coords[3] - line02Coords[0]) * (line01Coords[4] - line01Coords[1]));
            if (temp == 0)
            {
                returnCoord = null;
            }
            else
            {
                double k = ((line02Coords[3] - line02Coords[0]) * (line01Coords[1] - line02Coords[1])
               -
                (line01Coords[0] - line02Coords[0]) * (line02Coords[4] - line02Coords[1])) /
               temp;
                returnCoord[0] = k * (line01Coords[3] - line01Coords[0]) + line01Coords[0];
                returnCoord[1] = k * (line01Coords[4] - line01Coords[1]) + line01Coords[1];
            }
            return returnCoord;
        }

        /// <summary> 
        /// 判断等高线与直线是否相交
        /// </summary> 
        /// <param name="contoursCoords">等高线坐标，其长度为 2*n，n 表示等高线节点数目</param> 
        /// <param name="lineCoords">线段的坐标，长度为 6</param> 
        /// <param name="intersectCoord">out,如果有交点则返回交点坐标，长度为 2，否则为 null</param> 
        /// <returns>返回类型为 bool，如果为 true 表示相交，如果为 false 表示不相交</returns> 
        private bool JudgeCrossStatus(double[] contoursCoords, double[] lineCoords, out double[] intersectCoord)
        {
            intersectCoord = new double[2];
            bool returnResult = false;
            //判断直线与等高线上的每段线段是否相交
            double[] tempLineCoords;
            bool tempResult;
            for (int i = 0; i < contoursCoords.Length / 2 - 1; i++)
            {
                tempLineCoords = new double[6];
                tempLineCoords[0] = contoursCoords[2 * i];
                tempLineCoords[1] = contoursCoords[2 * i + 1];
                tempLineCoords[2] = 0d;
                tempLineCoords[3] = contoursCoords[2 * i + 2];
                tempLineCoords[4] = contoursCoords[2 * i + 3];
                tempLineCoords[5] = 0d;
                tempResult = Judge2LinesRelation(tempLineCoords, lineCoords, out intersectCoord);
                if (tempResult)//如果相交，则退出
                {
                    returnResult = true;
                    break;
                }
            }
            return returnResult;
        }

        //按从大到小的顺序排序
        /// <summary> 
        /// 根据给定坐标进行数据排序，如果直线端点坐标递增则按从小到大的顺序排列；
        /// 如果直线端点坐标递减则按从大到小的顺序排列
        /// </summary> 
        /// <param name="linePoints">直线端点坐标，长度为6</param> 
        /// <param name="insertPoints">插入点坐标，长度为2*n</param> 
        /// <returns>返回插入点的顺序</returns> 
        private int[] PointsSort(double[] linePoints, double[] insertPoints)
        {
            int[] returnResult = new int[insertPoints.Length / 2];
            double[] startPoint = new double[2], endPoint = new double[2];
            startPoint[0] = linePoints[0]; startPoint[1] = linePoints[1];
            endPoint[0] = linePoints[3]; endPoint[1] = linePoints[4];

            double temp;
            int tempI, i, j;
            for (i = 0; i < returnResult.Length; i++)
            {
                returnResult[i] = i;
            }
            if (startPoint[0] > endPoint[0])//按从大到小的顺序排列
            {
                for (i = 0; i < insertPoints.Length / 2; i++)
                {
                    for (j = i + 1; j < insertPoints.Length / 2; j++)
                    {
                        if (insertPoints[2 * j] > insertPoints[2 * i])
                        {
                            temp = insertPoints[2 * j];
                            insertPoints[2 * j] = insertPoints[2 * i];
                            insertPoints[2 * i] = temp;
                            tempI = returnResult[i];
                            returnResult[i] = returnResult[j];
                            returnResult[j] = tempI;
                        }
                    }
                }
            }
            else if (startPoint[0] < endPoint[0])//按从小到大的顺序排列
            {
                for (i = 0; i < insertPoints.Length / 2; i++)
                {
                    for (j = i + 1; j < insertPoints.Length / 2; j++)
                    {
                        if (insertPoints[2 * j] < insertPoints[2 * i])
                        {
                            temp = insertPoints[2 * j];
                            insertPoints[2 * j] = insertPoints[2 * i];
                            insertPoints[2 * i] = temp;
                            tempI = returnResult[i];
                            returnResult[i] = returnResult[j];
                            returnResult[j] = tempI;
                        }
                    }
                }
            }
            else if (startPoint[0] == endPoint[0])//比较Y方向
            {
                if (startPoint[1] > endPoint[1])//按从大到小的顺序排列
                {
                    for (i = 0; i < insertPoints.Length / 2; i++)
                    {
                        for (j = i + 1; j < insertPoints.Length / 2; j++)
                        {
                            if (insertPoints[2 * j + 1] > insertPoints[2 * i + 1])
                            {
                                temp = insertPoints[2 * j + 1];
                                insertPoints[2 * j + 1] = insertPoints[2 * i + 1];
                                insertPoints[2 * i + 1] = temp;
                                tempI = returnResult[i];
                                returnResult[i] = returnResult[j];
                                returnResult[j] = tempI;
                            }
                        }
                    }
                }
                else if (startPoint[1] < endPoint[1])//按从小到大的顺序排列
                {
                    for (i = 0; i < insertPoints.Length / 2; i++)
                    {
                        for (j = i + 1; j < insertPoints.Length / 2; j++)
                        {
                            if (insertPoints[2 * j + 1] < insertPoints[2 * i + 1])
                            {
                                temp = insertPoints[2 * j + 1];
                                insertPoints[2 * j + 1] = insertPoints[2 * i + 1];
                                insertPoints[2 * i + 1] = temp;
                                tempI = returnResult[i];
                                returnResult[i] = returnResult[j];
                                returnResult[j] = tempI;
                            }
                        }
                    }
                }
            }
            return returnResult;
        }

        private void 搜索首曲线button_Click(object sender, EventArgs e)
        {
            //先判断是否存在图层“自动等高线”
            bool isIn = false;
            for (int i = 0; i < AcadDoc.Layers.Count; i++)
            {
                if (AcadDoc.Layers.Item(i).Name == "自动等高线")
                {
                    isIn = true;
                    break;
                }
            }
            if (!isIn)
            {
                MessageBox.Show("文件中不存在图层“自动等高线”，请新建该图层！");
                return;
            }
            //用于赋予高程值的等高线对象的句柄
            ArrayList ContoursHandleID = new ArrayList();
            //新建的等高线对象，其数目与ContoursHandleID数目相同
            ArrayList NewContours = new ArrayList();
            if (ElvPointsObj != null)
            {
                double elevation = 0d;//高程值 
                double height = 0d;//文字高度
                double[] selectionEdge;//设置选择范围边界
                double[] startPoint;//文字插入点坐标
                double rotAngle = 0d;//文字旋转角度，单位为弧度
                for (int i = 0; i < ElvPointsObj.Count; i++)
                {
                    AcadObject TextObj = (AcadObject)ElvPointsObj[i];
                    selectionEdge = new double[15];
                    startPoint = new double[3];
                    if (TextObj.ObjectName == "AcDbText")//为单行文本对象时
                    {
                        AcadText textObj = (AcadText)TextObj;
                        height = textObj.Height;
                        startPoint = (double[])textObj.InsertionPoint;
                        elevation = ((double[])ElvPointsCoord[i])[2];
                        rotAngle = textObj.Rotation;
                    }
                    else if (TextObj.ObjectName == "AcDbMText")//为多行文本对象时
                    {
                        AcadMText mtextObj = (AcadMText)TextObj;
                        height = mtextObj.Height;
                        startPoint = (double[])mtextObj.InsertionPoint;
                        elevation = ((double[])ElvPointsCoord[i])[2];
                        rotAngle = mtextObj.Rotation;
                    }
                    int length = elevation.ToString().Length;//文字长度
                    double textLength = length * height;
                    //定义选择集范围
                    selectionEdge[0] = startPoint[0];
                    selectionEdge[1] = startPoint[1];
                    selectionEdge[2] = startPoint[2];
                    selectionEdge[3] = selectionEdge[0] + textLength * Math.Cos(rotAngle);
                    selectionEdge[4] = selectionEdge[1] + textLength * Math.Sin(rotAngle);
                    selectionEdge[5] = startPoint[2];
                    selectionEdge[6] = selectionEdge[3] + height * Math.Sin(rotAngle);
                    selectionEdge[7] = selectionEdge[4] - height * Math.Cos(rotAngle);
                    selectionEdge[8] = startPoint[2];
                    selectionEdge[9] = selectionEdge[0] + height * Math.Sin(rotAngle);
                    selectionEdge[10] = selectionEdge[1] - height * Math.Cos(rotAngle);
                    selectionEdge[11] = startPoint[2];
                    selectionEdge[12] = startPoint[0];
                    selectionEdge[13] = startPoint[1];
                    selectionEdge[14] = startPoint[2];
                    double[] deltaXY = new double[2];
                    deltaXY[0] = 0.1 * length * Math.Cos(rotAngle);
                    deltaXY[1] = 0.1 * length * Math.Sin(rotAngle);
                    for (int u = 0; u < 10; u++)
                    {
                        //定义选择集范围
                        selectionEdge[0] += -deltaXY[0];
                        selectionEdge[1] += -deltaXY[1];
                        selectionEdge[3] += deltaXY[0];
                        selectionEdge[4] += deltaXY[1];
                        selectionEdge[6] += deltaXY[0];
                        selectionEdge[7] += deltaXY[1];
                        selectionEdge[9] += -deltaXY[0];
                        selectionEdge[10] += -deltaXY[1];
                        selectionEdge[12] = selectionEdge[0];
                        selectionEdge[13] = selectionEdge[1];
                        ArrayList tempContoursArray = new ArrayList();
                        //定义选择集
                        AcadSelectionSet tempSelectionSet;
                        tempSelectionSet = AcadDoc.SelectionSets.Add("TempNewSelectionSet02");
                        Int16[] FilterType = new Int16[1];
                        object[] FilterData = new object[1];
                        FilterType[0] = 8;
                        FilterData[0] = ContoursComboBox.Text;
                        tempSelectionSet.SelectByPolygon(AcSelect.acSelectionSetCrossingPolygon,
                       selectionEdge, FilterType, FilterData);

                        if (tempSelectionSet.Count == 2)//如果搜索到两个
                        {
                            double[] tempContoursCoord, tempContoursCoord02;
                            foreach (AcadObject tempAcadObj in tempSelectionSet)
                            {
                                switch (tempAcadObj.ObjectName)
                                {
                                    case "AcDbPolyline"://如果为多段线
                                        {
                                            AcadLWPolyline tempLWPolyline =
                                           (AcadLWPolyline)tempAcadObj;
                                            tempContoursCoord =
                                           (double[])tempLWPolyline.Coordinates;
                                            tempContoursArray.Add(tempLWPolyline.Handle);
                                            tempContoursArray.Add(tempContoursCoord);
                                            break;
                                        }
                                    case "AcDb2dPolyline"://如果为二维多段线
                                        {
                                            AcadPolyline tempPolyline = (AcadPolyline)tempAcadObj;
                                            tempContoursCoord02 =
                                           (double[])tempPolyline.Coordinates;
                                            tempContoursCoord = new double[2 *
                                           tempContoursCoord02.Length / 3];
                                            for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                            {
                                                tempContoursCoord[2 * j] = tempContoursCoord02[3 *
                                               j];
                                                tempContoursCoord[2 * j + 1] = tempContoursCoord02[3
                                               * j + 1];
                                            }
                                            tempContoursArray.Add(tempPolyline.Handle);
                                            tempContoursArray.Add(tempContoursCoord);
                                            break;
                                        }
                                    case "AcDbSpline"://如果为样条曲线
                                        {
                                            AcadSpline tempSpline = (AcadSpline)tempAcadObj;
                                            tempContoursCoord02 =
                                           (double[])tempSpline.ControlPoints;
                                            tempContoursCoord = new double[2 *
                                           tempContoursCoord02.Length / 3];
                                            for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                            {
                                                tempContoursCoord[2 * j] = tempContoursCoord02[3 *
                                               j];
                                                tempContoursCoord[2 * j + 1] = tempContoursCoord02[3
                                               * j + 1];
                                            }
                                            tempContoursArray.Add(tempSpline.Handle);
                                            tempContoursArray.Add(tempContoursCoord);
                                            break;
                                        }
                                    case "AcDb3dPolyline"://如果为三维多段线
                                        {
                                            Acad3DPolyline temp3dPoly =
                                           (Acad3DPolyline)tempAcadObj;
                                            tempContoursCoord02 =
                                           (double[])temp3dPoly.Coordinates;
                                            tempContoursCoord = new double[2 *
                                           tempContoursCoord02.Length / 3];
                                            for (int j = 0; j < tempContoursCoord.Length / 2; j++)
                                            {
                                                tempContoursCoord[2 * j] = tempContoursCoord02[3 *
                                               j];
                                                tempContoursCoord[2 * j + 1] = tempContoursCoord02[3
                                               * j + 1];
                                            }
                                            tempContoursArray.Add(temp3dPoly.Handle);
                                            tempContoursArray.Add(tempContoursCoord);
                                            break;
                                        }
                                }
                            }
                            //赋予高程值
                            if (tempContoursArray.Count > 0)
                            {
                                double[] tempDrawPolyline;
                                AcadPolyline tempDrawContour;
                                for (int k = 0; k < tempContoursArray.Count / 2; k++)
                                {
                                    //先判断是否已经为该对象赋予高程值了
                                    string tempObjectHandle = (string)tempContoursArray[2 * k];
                                    if (!ContoursHandleID.Contains(tempObjectHandle))//如果不包含该Handle值
                                    {
                                        double[] tempDrawPolyline02 = (double[])tempContoursArray[2
                                       * k + 1];
                                        tempDrawPolyline = new double[3 * tempDrawPolyline02.Length
                                       / 2];
                                        for (int p = 0; p < tempDrawPolyline02.Length / 2; p++)
                                        {
                                            tempDrawPolyline[3 * p] = tempDrawPolyline02[2 * p];
                                            tempDrawPolyline[3 * p + 1] = tempDrawPolyline02[2 * p
                                           + 1];
                                            tempDrawPolyline[3 * p + 2] = elevation;
                                        }
                                        tempDrawContour =
                                       AcadDoc.ModelSpace.AddPolyline(tempDrawPolyline);
                                        tempDrawContour.Elevation = elevation;
                                        tempDrawContour.Layer = "自动等高线";
                                        ContoursHandleID.Add(tempObjectHandle);
                                        NewContours.Add(tempDrawContour);
                                    } 
                                    else//如果已经存在，则判断一下现在获取高程值与以前设置是否相同，
                                        //如果不同则设置线的颜色为黄色，表示警告！
                                    {
                                        AcadPolyline tempDrawContour02 =
                                       (AcadPolyline)NewContours[ContoursHandleID.IndexOf(tempObjectHandle)];
                                        if (tempDrawContour02.Elevation != elevation)
                                            tempDrawContour02.color = ACAD_COLOR.acYellow;
                                    }
                                }
                            }
                            AcadDoc.SelectionSets.Item("TempNewSelectionSet02").Delete();
                            break;
                        }
                        AcadDoc.SelectionSets.Item("TempNewSelectionSet02").Delete();
                    }
                }
            }
        }
    }
}
